package com.cy.common.config;

import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.mgt.RememberMeManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import java.util.LinkedHashMap;

@Configuration
public class SpringShiroConfig {
    /*@Bean
    public DefaultWebSecurityManager securityManager(
            Realm realm){
        DefaultWebSecurityManager securityManager =
                new DefaultWebSecurityManager();
        securityManager.setRealm(realm);
        return securityManager;
    }*/
    @Bean //bean的名字默认为方法名
    //@Scope("singleton")//默认
    public SecurityManager securityManager(Realm realm,
                                           CacheManager cacheManager,
                                           RememberMeManager rememberMeManager,
                                           SessionManager sessionManager){
        DefaultWebSecurityManager securityManager=
                new DefaultWebSecurityManager();
        securityManager.setRealm(realm);
        securityManager.setCacheManager(cacheManager);
        securityManager.setRememberMeManager(rememberMeManager);
        securityManager.setSessionManager(sessionManager);
        return securityManager;
    }

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean (
            SecurityManager securityManager){
        ShiroFilterFactoryBean sfBean=new ShiroFilterFactoryBean();
       //定义setSecurityManager(securityManager) 基于此对象进行认证检测
        sfBean.setSecurityManager(securityManager);
        sfBean.setLoginUrl("/doLoginUI");
        //定义map指定请求过滤规则(哪些资源允许匿名访问,哪些必须认证访问)
        LinkedHashMap<String,String> map= new LinkedHashMap<>();
        //静态资源允许匿名访问:"anon"
        map.put("/bower_components/**","anon");
        map.put("/build/**","anon");
        map.put("/dist/**","anon");
        map.put("/plugins/**","anon");

        map.put("/user/doLogin", "anon");
        map.put("/doLogout","logout");
        //除了匿名访问的资源,其它都要认证("authc")后访问
        //map.put("/**","authc");//写在匿名访问的后面（有顺序要求）
        map.put("/**","user");//可以从用户浏览器cookie中读取账号信息进行身份认证
        sfBean.setFilterChainDefinitionMap(map);
        return sfBean;

    }

    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
        return new LifecycleBeanPostProcessor();
    }

    @DependsOn("lifecycleBeanPostProcessor")
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
        return new DefaultAdvisorAutoProxyCreator();
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor
    authorizationAttributeSourceAdvisor(SecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor advisor=
                new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }

    @Bean
    public CacheManager shiroCacheManager(){
        return new MemoryConstrainedCacheManager();
    }

    @Bean
    public RememberMeManager rememberMeManager() {
        CookieRememberMeManager cManager=
                new CookieRememberMeManager();
        SimpleCookie cookie=new SimpleCookie("rememberMe");
        cookie.setMaxAge(7*24*60*60);
        cManager.setCookie(cookie);
        return cManager;
    }

    @Bean
    public SessionManager sessionManager() {
        DefaultWebSessionManager sessionManager=new DefaultWebSessionManager();
        sessionManager.setGlobalSessionTimeout(60*60*1000);//设置超时时间为1个小时
        //session对象由谁服务端创建,
        //但这个对象创建好以后,会将其jsessionid以会话cookie的形式写到客户端
        //客户端再访问服务器时,会携带jsessionid到服务端,然后基于这个id找到session.
        sessionManager.setSessionIdUrlRewritingEnabled(false);//关闭url重写.
        //一般假如浏览器禁用了cookie,我们可重写url,
        //此时会在url的后面添加一个jsessionid,服务端可以基于这个id为客户端找到对应session
        return sessionManager;
    }
}
